/*
 * Copyright 2007. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the GNU Lesser General Public License, Version 2. You
 * can find a copy of the license at:
 * 
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */
package com.sinai.mshab.server.sql;

import com.sinai.mshab.client.MSHABConfig;

/**
 * This class offers a place to store information about a database filters. This
 * information is then utilized to construct WHERE clauses.
 * 
 * @author Arthur Kalmenson
 */
public class DbFilter extends DbField {

	/**
	 * The operator used to compare the field to the value.
	 */
	private String operator;

	/**
	 * Creates a new DbFilter with the given information. Note, all parameters
	 * must be instantiated and not empty otherwise a
	 * {@link IllegalArgumentException} will be thrown. Furthermore, operator
	 * must be a valid SQL comparison operator.
	 * 
	 * @param table
	 *            the name of the table where the field resides.
	 * @param field
	 *            the field in the table by which we want to filter.
	 * @param value
	 *            the value the field should hold or should be compared to.
	 * @param operator
	 *            the operator to be used between the field and the value.
	 */
	public DbFilter(String table, String field, String value, String operator) {

		super(table, field, value);

		// check to insure that the input is not null.
		if (operator == null) {
			throw new IllegalArgumentException(
					MSHABConfig.MSHAB_ERROR_NULL_ARGS);
		}

		// check to insure that the input is not empty.
		if (operator.trim().isEmpty()) {
			throw new IllegalArgumentException(
					MSHABConfig.MSHAB_ERROR_EMPTY_ARGS);
		}

		if (!validOperator(operator)) {
			throw new IllegalArgumentException(
					"Not a valid SQL comparison operator: " + operator);
		}

		// otherwise we have clean data and so we may continue.
		this.operator = operator;
	}

	/**
	 * Returns the operator that is to be used to compare the field to the
	 * value.
	 * 
	 * @return the operator that is to be used to compare the field to the
	 *         value.
	 */
	public String getOperator() {
		return operator;
	}

	public boolean equals(Object obj) {

		boolean result = true;

		if (obj == null) {
			result = false;
		} else if (!(obj instanceof DbFilter)) {
			result = false;
		} else {

			// now we know it's a DbField, we need to compare DbField's various
			// fields.
			DbFilter compareWhere = (DbFilter) obj;

			// both table and field must always be instantiated and not empty,
			// so the only difference between them is that one can have a value
			// and the other one can be missing a value.
			if (!compareWhere.getTable().equals(getTable())) {
				result = false;
			} else if (!compareWhere.getField().equals(getField())) {
				result = false;
			} else if (!compareWhere.getValue().equals(getValue())) {
				result = false;
			} else if (!compareWhere.getOperator().equals(operator)) {
				result = false;
			}
		}

		return result;
	}

	public int hashCode() {
		return getTable().hashCode() + getField().hashCode()
				+ getValue().hashCode() + operator.hashCode();
	}

	/**
	 * Returns true if operator is a valid SQL range or equality operator and
	 * false otherwise.
	 * 
	 * @param operator
	 *            a SQL operator.
	 * @return true operator is a valid SQL operator and false otherwise.
	 */
	private boolean validOperator(String operator) {

		boolean valid = false;

		if (operator.equals("<") || operator.equals(">")
				|| operator.equals("<=") || operator.equals(">=")
				|| operator.equals("=") || operator.equals("<>")) {
			valid = true;
		}

		return valid;
	}
}